home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / demos / OpenGL / stonehenge / callbacks.c++ < prev    next >
C/C++ Source or Header  |  1996-11-11  |  11KB  |  467 lines

  1. /*
  2.  * (c) Copyright 1993, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software for
  6.  * any purpose and without fee is hereby granted, provided that the above
  7.  * copyright notice appear in all copies and that both the copyright notice
  8.  * and this permission notice appear in supporting documentation, and that
  9.  * the name of Silicon Graphics, Inc. not be used in advertising
  10.  * or publicity pertaining to distribution of the software without specific,
  11.  * written prior permission.
  12.  *
  13.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  14.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  15.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  16.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  17.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  18.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  19.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  20.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  21.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  22.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  23.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  24.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  25.  *
  26.  * U.S. GOVERNMENT RESTRICTED RIGHTS LEGEND
  27.  * Use, duplication, or disclosure by the Government is subject to
  28.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  29.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  30.  * clause at DFARS 252.227-7013 and/or in similar or successor
  31.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  32.  * Unpublished-- rights reserved under the copyright laws of the
  33.  * United States.  Contractor/manufacturer is Silicon Graphics,
  34.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  35.  *
  36.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  37.  */
  38. #include <X11/Intrinsic.h>
  39. #include <X11/keysym.h>
  40. #include <Xm/Xm.h>
  41.  
  42. #include <GL/glu.h>
  43. #include <GL/glx.h>
  44. #include <GL/GLwMDrawA.h>
  45.  
  46. #include <math.h>
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <sys/time.h>
  50.  
  51. #include "atmosphere.h"
  52. #include "scene.h"
  53.  
  54. #include "callbacks.h"
  55.  
  56. int cb_demo_mode = 0;
  57. float demo_time;
  58.  
  59. extern Widget glw;
  60. extern XtAppContext app_context;
  61. GLXContext glx_context;
  62.  
  63. static int needs_wp = 0;
  64. static XtWorkProcId workproc = NULL;
  65.  
  66. static int winx, winy;
  67.  
  68. static int button_down = 0;
  69. int mousex, mousey;
  70. /* What's moving */
  71. GLint target;
  72.  
  73. /* Location of the telescope */
  74. GLfloat tx, ty;
  75.  
  76. /* Movements of the camera position to be applied at the next redraw */
  77. float rot_pendx = 0, rot_pendz = 0, trans_pend = 0;
  78.  
  79. /* How fast the camera is moving */
  80. float trans_speed = 0;
  81.  
  82. /* This is how fast demo time moves relative to real time */
  83. GLfloat time_scale = 0;
  84.  
  85. TimeDate last_update;
  86.  
  87. float last_time = 0;
  88. const float time_fudge = 1000;
  89. inline unsigned long current_time()
  90. {
  91.   struct timeval time;
  92.   gettimeofday(&time, NULL);
  93.   return (time.tv_sec * 1000000 + time.tv_usec);
  94. }
  95.  
  96. inline float clamp(float x, float min, float max)
  97. {
  98.   if (x < min) return min;
  99.   else if (x > max) return max;
  100.   else return x;
  101. }
  102.  
  103. static void add_workproc()
  104. {
  105.   needs_wp++;
  106.   if (workproc == NULL)
  107.     workproc = XtAppAddWorkProc(app_context, drawWP, NULL);
  108. }
  109.  
  110. static void remove_workproc()
  111. {
  112.   needs_wp--;
  113.   if (needs_wp == 0) {
  114.     XtRemoveWorkProc(workproc);
  115.     workproc = NULL;
  116.   } else if (needs_wp < 0) {
  117.     fprintf(stderr, "Internal Error:  No workproc to remove!\n");
  118.     needs_wp = 0;
  119.     workproc = NULL;
  120.   }
  121. }
  122.  
  123. static void reset_viewer()
  124. {
  125.   scene_viewer_center();
  126. }
  127.  
  128. void intToggleCB(Widget w, XtPointer client_data, XtPointer call_data)
  129. {
  130.   int *data;
  131.   XmToggleButtonCallbackStruct *ptr;
  132.   ptr = (XmToggleButtonCallbackStruct *)call_data;
  133.   data = (int *)client_data;
  134.   *data = ptr->set;
  135.   // This redraw may or may not be needed - do it to be safe
  136.   drawWP(NULL);
  137. }
  138.  
  139.  
  140. void initCB(Widget w)
  141. {
  142.   Arg args[1];
  143.   XVisualInfo *vi;
  144.  
  145.   glw = w;
  146.  
  147.   XtSetArg(args[0], GLwNvisualInfo, &vi);
  148.   XtGetValues(w, args, 1);
  149.  
  150.   glx_context = glXCreateContext(XtDisplay(w), vi, 0, GL_FALSE);
  151.   GLwDrawingAreaMakeCurrent(w, glx_context);
  152.  
  153.   scene_init();
  154.  
  155.   last_update.read_time();
  156.  
  157.   resetViewerCB(NULL, NULL, NULL);
  158. }
  159.  
  160. void exposeCB(Widget w)
  161. {
  162.   drawWP(NULL);
  163. }
  164.  
  165. void resizeCB(Widget w, XtPointer client_data, XtPointer call)
  166. {
  167.   GLwDrawingAreaCallbackStruct *call_data;
  168.  
  169.   GLwDrawingAreaMakeCurrent(w, glx_context);
  170.  
  171.   call_data = (GLwDrawingAreaCallbackStruct *)call;
  172.  
  173.   winx = call_data->width;
  174.   winy = call_data->height;
  175.   
  176.   glViewport(0, 0, winx, winy);
  177.   
  178.   aspect = (GLfloat)winx / (GLfloat)winy;
  179. }
  180.  
  181. void inputCB(Widget w, XtPointer client_data, XtPointer call_data)
  182. {
  183.   GLwDrawingAreaCallbackStruct *call;
  184.  
  185.   char buffer[5];
  186.   int bufsize = 5;
  187.   KeySym key;
  188.   XComposeStatus compose;
  189.  
  190.   float dx, dy, r1, r2;
  191.  
  192.   GLwDrawingAreaMakeCurrent(w, glx_context);
  193.  
  194.   call = (GLwDrawingAreaCallbackStruct *)call_data;
  195.  
  196.   switch(call->event->type) {
  197.   case ButtonPress:
  198.     last_time = current_time();
  199.     button_down = call->event->xbutton.button;
  200.     mousex = call->event->xbutton.x;
  201.     mousey = call->event->xbutton.y;
  202.     /* Determine if the target should be the camera position 
  203.      * or the telescope */
  204.     if (use_telescope) {
  205.       scene_get_position_telescope(&tx, &ty);
  206.       scene_get_radius_telescope(&r1);
  207.       dx = (tx + .5) - ((GLfloat)(winx - mousex)/(GLfloat)winx);
  208.       dy = (ty + .5) - ((GLfloat)(winy - mousey)/(GLfloat)winy);
  209.       r2 = sqrt(dx*dx + dy*dy);
  210.       if (r2 < r1) target = name_telescope;
  211.       else target = name_background;
  212.     } else target = name_background;
  213.     add_workproc();
  214.     break;
  215.   case ButtonRelease:
  216.     if (call->event->xbutton.button == Button3) {
  217.       /* Use Button3 to stop */
  218.       if (trans_speed) remove_workproc();
  219.       trans_speed = 0;
  220.     }
  221.     remove_workproc();
  222.     button_down = 0;
  223.     break;
  224.   case MotionNotify:
  225.     switch(button_down) {
  226.     case Button1:
  227.       /* Use Button1 to control the way in which the viewer is looking 
  228.        * or to move the telescope around */
  229.       if (target == name_background) {
  230.     dx = (float)(call->event->xmotion.x - mousex) / (float)winx;
  231.     dy = (float)(call->event->xmotion.y - mousey) / (float)winy;
  232.     rot_pendx -= dy * fov;
  233.     rot_pendz -= dx * fov;
  234.       } else {
  235.     dx = (float)(mousex - call->event->xmotion.x) / (float)winx;
  236.     dy = (float)(mousey - call->event->xmotion.y) / (float)winy;
  237.     tx += dx;
  238.     ty += dy;
  239.     tx = clamp(tx, -.5, .5);
  240.     ty = clamp(ty, -.5, .5);
  241.     scene_position_telescope(tx, ty);
  242.       }
  243.       break;
  244.     case Button2:
  245.       /* Use Button2 to change speed */
  246.       dx = (float)(mousex - call->event->xmotion.x) / 
  247.     (float)winx;
  248.       if (dx && !trans_speed) add_workproc();
  249.       else if (!dx && trans_speed) remove_workproc();
  250.       if (dx)
  251.       trans_speed += dx;
  252.       else
  253.       trans_speed = 0;
  254.       break;
  255.     }
  256.     mousex = call->event->xmotion.x;
  257.     mousey = call->event->xmotion.y;
  258.     break;
  259.   case KeyPress:
  260.     XLookupString(&(call->event->xkey), buffer, bufsize, &key, &compose);
  261.     if (key == XK_Escape) exit(0);
  262.     break;                            
  263.   default:
  264.     break;
  265.   }
  266. }
  267.  
  268. const float speed_t = .5;
  269. const float speed_r = 15.;
  270. const float speed_rx = 10.;
  271. void demo_mode_update(float dt)
  272. {
  273.   float t;
  274.   
  275.   if (!cb_demo_mode) return;
  276.   
  277.   dt /= 1000000;
  278.   demo_time += dt;
  279.   
  280.   t = demo_time;
  281.   
  282.   if (t < 10.5) {
  283.     trans_speed = speed_t;
  284.     return;
  285.   } else t -= 10.5;
  286.   
  287.   if (t < 1) {
  288.     trans_speed = 0;
  289.     rot_pendz = 0;
  290.     return;
  291.   } else t -= 1;
  292.   
  293.   if (t < 3.) {
  294.     trans_speed = 0.;
  295.     rot_pendz = dt * speed_r;
  296.     return;
  297.   } else t -= 3.;
  298.   
  299.   if (t < 2.) {
  300.     rot_pendx = -dt * speed_rx;
  301.     return;
  302.   } else t -= 2.;
  303.  
  304.   if (t < 2.) {
  305.     return;
  306.   } else t -= 2.;
  307.  
  308.   if (t < 2.) {
  309.     rot_pendx = dt * speed_rx;
  310.     return;
  311.   } else t -= 2.;
  312.   
  313.  
  314.   if (t < 3.) {
  315.     trans_speed = 0.;
  316.     rot_pendz = dt * speed_r;
  317.     return;
  318.   } else t -= 3.;
  319.  
  320.   if (t < 30.) {
  321.     trans_speed  = speed_t;
  322.     rot_pendz = 0;
  323.     return;
  324.   } else t -= 30.;
  325.   
  326.   if (t < 1.) {
  327.     trans_speed = 0;
  328.     return;
  329.   } else t -= 1.;
  330.  
  331.   if (t < 1.3) {
  332.     rot_pendz = -dt * speed_r;
  333.     return;
  334.   } else t -= 1.3;
  335.  
  336.   // Pan back to see entire thing
  337.   if (t < 23) {
  338.     trans_speed = speed_t;
  339.     return;
  340.   } else t -= 23;
  341.  
  342.   // Hold before starting over
  343.   if (t < 20) {
  344.     trans_speed = 0;
  345.     return;
  346.   }
  347.   else t -= 20;
  348.  
  349.   demo_time = 0.;
  350.   reset_viewer();
  351. }
  352.  
  353. Boolean drawWP(XtPointer data)
  354. {
  355.   /* Right now, there's two completely independent time measurements:
  356.    * one for the time of day in the demo and one for changing the camera
  357.    * position */
  358.   TimeDate t, dt;
  359.   float elapsed_time, time;
  360.  
  361.   if (time_scale != 0.0) {
  362.     t.read_time();
  363.     dt = (t - last_update) * time_scale;
  364.     scene_inc_time(dt);
  365.     last_update = t;
  366.   }
  367.  
  368.   time = current_time();
  369.   if (time - last_time > time_fudge) {
  370.     elapsed_time = time - last_time;
  371.     demo_mode_update(elapsed_time);
  372.     trans_pend = trans_speed * (elapsed_time / 1000000);
  373.     last_time = time;
  374.   }
  375.  
  376.   scene_viewer_rotatex(rot_pendx);
  377.   scene_viewer_rotatez(rot_pendz);
  378.   scene_viewer_translate(trans_pend);
  379.   rot_pendx = 0;
  380.   rot_pendz = 0;
  381.   trans_pend = 0;
  382.  
  383.   GLwDrawingAreaMakeCurrent(glw, glx_context);
  384.   scene_render();
  385.   /* This is a total hack */
  386. //  if (!use_antialias)
  387. GLwDrawingAreaSwapBuffers(glw);
  388.  
  389.   return FALSE;
  390. }
  391.  
  392. void weatherCB(Widget w, XtPointer client_data, XtPointer call_data)
  393. {
  394.   Weather *data;
  395.   XmToggleButtonCallbackStruct *ptr;
  396.   ptr = (XmToggleButtonCallbackStruct *)call_data;
  397.   if (ptr->set) scene_set_weather(*((Weather *)client_data));
  398.   drawWP(NULL);
  399. }
  400.  
  401. void currentTimeCB(Widget w)
  402. {
  403.   scene_set_time(TimeDate().read_time());
  404.   drawWP(NULL);
  405. }
  406.  
  407. void time10amCB(Widget w)
  408. {
  409.   scene_set_time(TimeDate(10, 0));
  410.   drawWP(NULL);
  411. }
  412.  
  413. void time12pmCB(Widget w)
  414. {
  415.   scene_set_time(TimeDate(12, 0));
  416.   drawWP(NULL);
  417. }
  418.  
  419. void time4pmCB(Widget w)
  420. {
  421.   scene_set_time(TimeDate(16, 0));
  422.   drawWP(NULL);
  423. }
  424.  
  425. void timeSpeedCB(Widget w, XtPointer client_data, XtPointer call_data)
  426. {
  427.   
  428.   if (!((XmToggleButtonCallbackStruct *)call_data)->set) return;
  429.   time_scale =  *(int *)client_data;
  430.   if (time_scale == 0.0) remove_workproc();
  431.   else add_workproc();
  432.   last_update.read_time();
  433. }
  434.  
  435. void demo_modeCB(Widget w, XtPointer client_data, XtPointer call_data)
  436. {
  437.   int val  = ((XmToggleButtonCallbackStruct *)call_data)->set;
  438.   if (!val) {
  439.     remove_workproc();
  440.     resetViewerCB(NULL, NULL, NULL);
  441.     last_time = current_time();
  442.   } else {
  443.     reset_viewer();
  444.     add_workproc();
  445.     trans_speed = 0;
  446.     demo_time = 0;
  447.     rot_pendx = -5;
  448.   }
  449.   cb_demo_mode = val;
  450.   drawWP(NULL);
  451. }
  452.  
  453. void resetViewerCB(Widget w, XtPointer client_data, XtPointer call_data)
  454. {
  455.   trans_speed = 0;
  456.   rot_pendx = rot_pendz = trans_pend = 0;
  457.   rot_pendx = -5;
  458.   reset_viewer();
  459.   return;
  460. }
  461.      
  462.  
  463. void exitCB(Widget w, XtPointer client_data, XtPointer call_data)
  464. {
  465.   exit(0);
  466. }
  467.